package org.convallaria.infrastruct.ce.monitor;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.convallaria.infrastruct.ce.config.CacheMonitoringConfig;
import org.convallaria.infrastruct.ce.util.CacheUtils;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.actuate.endpoint.annotation.Selector;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 缓存监控端点
 * 提供缓存状态和统计信息
 * 
 * @author gjh
 * @since 2024-09-24
 */
@Slf4j
@Component
@Endpoint(id = "cache")
@RequiredArgsConstructor
public class CacheMonitor {

    private final CacheManager cacheManager;
    private final CacheMonitoringConfig cacheMonitoringConfig;
    private final CacheUtils cacheUtils;

    // 缓存操作统计
    private final AtomicLong totalHits = new AtomicLong(0);
    private final AtomicLong totalMisses = new AtomicLong(0);
    private final AtomicLong totalEvictions = new AtomicLong(0);

    /**
     * 获取所有缓存信息
     */
    @ReadOperation
    public Map<String, Object> getAllCacheInfo() {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 基本统计信息
            result.put("totalCaches", cacheManager.getCacheNames().size());
            result.put("totalHits", totalHits.get());
            result.put("totalMisses", totalMisses.get());
            result.put("totalEvictions", totalEvictions.get());
            
            // 计算总体命中率
            long hits = totalHits.get();
            long misses = totalMisses.get();
            double hitRatio = (hits + misses) > 0 ? (double) hits / (hits + misses) : 0.0;
            result.put("overallHitRatio", hitRatio);
            
            // 各缓存详细信息
            Map<String, Object> caches = new HashMap<>();
            for (String cacheName : cacheManager.getCacheNames()) {
                caches.put(cacheName, getCacheInfo(cacheName));
            }
            result.put("caches", caches);
            
            // 监控配置信息
            result.put("monitoringEnabled", cacheMonitoringConfig != null);
            
        } catch (Exception e) {
            log.error("获取缓存信息失败", e);
            result.put("error", e.getMessage());
        }
        
        return result;
    }

    /**
     * 获取指定缓存信息
     */
    @ReadOperation
    public Map<String, Object> getCacheInfo(@Selector String cacheName) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            Cache cache = cacheManager.getCache(cacheName);
            if (cache == null) {
                result.put("error", "缓存不存在: " + cacheName);
                return result;
            }
            
            result.put("name", cacheName);
            result.put("nativeCache", cache.getNativeCache().getClass().getSimpleName());
            
            // 获取缓存统计信息
            CacheUtils.CacheStatistics stats = cacheUtils.getStatistics(cacheName);
            result.put("statistics", stats);
            
            // 这里可以添加更多缓存特定的信息
            // 例如：Redis的info命令结果，Caffeine的stats等
            
        } catch (Exception e) {
            log.error("获取缓存信息失败: {}", cacheName, e);
            result.put("error", e.getMessage());
        }
        
        return result;
    }

    /**
     * 记录缓存命中
     */
    public void recordHit() {
        totalHits.incrementAndGet();
        if (cacheMonitoringConfig != null) {
            cacheMonitoringConfig.recordCacheHit();
        }
    }

    /**
     * 记录缓存未命中
     */
    public void recordMiss() {
        totalMisses.incrementAndGet();
        if (cacheMonitoringConfig != null) {
            cacheMonitoringConfig.recordCacheMiss();
        }
    }

    /**
     * 记录缓存驱逐
     */
    public void recordEviction() {
        totalEvictions.incrementAndGet();
        if (cacheMonitoringConfig != null) {
            cacheMonitoringConfig.recordCacheEviction();
        }
    }

    /**
     * 重置统计信息
     */
    public void resetStatistics() {
        totalHits.set(0);
        totalMisses.set(0);
        totalEvictions.set(0);
        log.info("缓存统计信息已重置");
    }

    /**
     * 获取缓存健康状态
     */
    @ReadOperation
    public Map<String, Object> getHealth() {
        Map<String, Object> result = new HashMap<>();
        
        try {
            boolean healthy = true;
            
            // 检查缓存管理器是否可用
            if (cacheManager == null) {
                healthy = false;
            }
            
            // 检查各缓存是否可用
            Map<String, String> cacheStatus = new HashMap<>();
            for (String cacheName : cacheManager.getCacheNames()) {
                try {
                    Cache cache = cacheManager.getCache(cacheName);
                    if (cache != null) {
                        cacheStatus.put(cacheName, "UP");
                    } else {
                        cacheStatus.put(cacheName, "DOWN");
                        healthy = false;
                    }
                } catch (Exception e) {
                    cacheStatus.put(cacheName, "ERROR: " + e.getMessage());
                    healthy = false;
                }
            }
            
            result.put("status", healthy ? "UP" : "DOWN");
            result.put("cacheStatus", cacheStatus);
            result.put("totalCaches", cacheManager.getCacheNames().size());
            
        } catch (Exception e) {
            log.error("获取缓存健康状态失败", e);
            result.put("status", "DOWN");
            result.put("error", e.getMessage());
        }
        
        return result;
    }
}
